﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using static System.Windows.Forms.VisualStyles.VisualStyleElement;

namespace SRTToolsV1
{
    public partial class FSRTTools : Form
    {
        private AutoTrStr tAutoTrStr { get; }
        public FSRTTools()
        {
            InitializeComponent();
            listBoxErrorList.Items.Clear();
            label翻译片段.Text = "";
            buttonOpenMid.Enabled = false;
            buttonSaveSrt.Enabled = false;
            tabControlSour.SelectedIndex = 0;
            tAutoTrStr = new AutoTrStr(tSourInfoLines);
        }

        private void textBoxSourFile_DoubleClick(object sender, EventArgs e)
        {
            textBoxSourFile.Text = "";
            if (openFileDialog1.ShowDialog() == DialogResult.OK)
            {
                textBoxSourFile.Text=openFileDialog1.FileName;
            }
        }

        List<StrLineInfo> tSourInfoLines = new List<StrLineInfo>();
        Dictionary<int, StrLineInfo> tCNInfos = new Dictionary<int, StrLineInfo>();

        /// <summary>
        /// 打开字幕源文件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void buttonOpenSour_Click(object sender, EventArgs e)
        {
            label翻译片段.Text = "";
            tabControlSour.SelectedIndex = 0;
            tCNInfos.Clear();
            tabControlSour.SelectedIndex= 0;    
            int iCount = openSourFile(tSourInfoLines, textBoxSourFile.Text);
            switch (iCount)
            {
                case -1:
                    MessageBox.Show("输入对象为空!", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    break;
                case -2:
                    MessageBox.Show("目标文件不存在!", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    break;
                default:
                    MessageBox.Show("成功提取到信息：" + iCount.ToString());
                    buttonOpenMid.Enabled = true;
                    buttonSaveSrt.Enabled = false;
                    break;
            }
            // 展示精简字幕内容，保持标记序号，去掉时间戳，用于翻译
            if (iCount > 0)
            {
                richTextBoxSourSimple.Clear();
                for (int i = 0; i < iCount; i++)
                {
                    richTextBoxSourSimple.AppendText("[" + tSourInfoLines[i].index.ToString() + "]\r\n");
                    richTextBoxSourSimple.AppendText(tSourInfoLines[i].context + "\r");
                }
            }
        }

        /// <summary>
        /// 导入原始SRT文件
        /// </summary>
        /// <param name="tDestList"></param>
        /// <param name="sFileName"></param>
        /// <returns></returns>
        private int openSourFile(List<StrLineInfo> tDestList ,string sFileName)
        {
            if (tDestList != null)
            {
                tDestList.Clear();
                if (File.Exists(sFileName))
                {
                    List<string> tList = new List<string>(File.ReadAllLines(sFileName));
                    for (int i = 0; i < tList.Count; i++)
                    {
                        int iIndex = 0;
                        if  (int.TryParse(tList[i].Trim(), out iIndex))
                        {
                            int iPos = 1;
                            while (((i + iPos) < tList.Count)&& (tList[i + iPos].Trim().Length<3)&&(iPos>20)
                                &&(tList[i + iPos].Length>=3))
                                iPos++;

                            if (((i + iPos) < tList.Count)&&(iPos < 20))
                            {
                                string sSubTT2 ="";
                                string sSubTT3 = "";
                                if ((!string.IsNullOrEmpty(tList[i + iPos]))&&(tList[i + iPos].Length>=3))
                                {
                                    sSubTT2 = tList[i + iPos].Substring(0, 2);
                                    sSubTT3 = tList[i + iPos].Substring(0, 3);
                                }

                                int iTmp = 0;
                                string sInfo = "";
                                if (int.TryParse(sSubTT2, out iTmp) && (!int.TryParse(sSubTT3, out iTmp)))
                                {
                                    int inewidx = 0;
                                    for (int j = 0; j < tList.Count - i-iPos; j++)
                                        if (((i + iPos+1 + j) < tList.Count) && (!int.TryParse(tList[i + iPos + 1 + j].Trim(), out inewidx)))
                                            sInfo += tList[i + iPos + 1 + j] + "\r\n";
                                        else
                                            break;
                                }
                                tDestList.Add(new StrLineInfo(iIndex, tList[i + 1], sInfo.Trim()));
                            }
                            else
                                break;
                        }
                    }
                    return tDestList.Count;
                }
                else
                    return -2;
            }
            return -1;
        }
        private int openASSFile(List<StrLineInfo> tDestList, string sFileName)
        {
            string sPiece = ",,0000,0000,0000,,";
            sPiece = ",,0,0,0,,";
            if (tDestList != null)
            {
                tDestList.Clear();
                if (File.Exists(sFileName))
                {
                    List<string> tList = new List<string>(File.ReadAllLines(sFileName));
                    for (int i = 0; i < tList.Count; i++)
                    {
                        string sTmp = tList[i].Trim();
                        string sInfo = "";
                        if (sTmp.IndexOf(sPiece) >0)
                        {
                            if (sTmp.IndexOf("}")>0)
                                sInfo = sTmp.Substring(sTmp.IndexOf("}") + 1, sTmp.Length - sTmp.IndexOf("}") - 1);
                            else
                                sInfo = sTmp.Substring(sTmp.IndexOf(sPiece) + sPiece.Length, sTmp.Length - sTmp.IndexOf(sPiece) - sPiece.Length);
                            if (sInfo.IndexOf(@"\N") > 0)
                            {
                                sInfo = sInfo.Replace(@"\N", " ");
                                sTmp= sTmp.Replace(@"\N", " ");
                            }
                        }
                        tDestList.Add(new StrLineInfo(i + 1, sTmp, sInfo.Trim()));
                    }
                    return tDestList.Count;
                }
                else
                    return -2;
            }
            return -1;
        }

        /// <summary>
        /// 导入去掉时间戳的中间翻译结果文件
        /// </summary>
        /// <param name="tDestList"></param>
        /// <param name="sFileName"></param>
        /// <returns></returns>
        private int openSimpleFile(Dictionary<int, StrLineInfo> tDestList, string sFileName)
        {
            if (tDestList == null)
                return -1;
            if (File.Exists(sFileName))
            {
                return openSimpleFile(tDestList, File.ReadAllLines(sFileName));
            }
            else
                return -2;
        }

        private bool chechIndex(string sLine,out int iIndex)
        {
            iIndex = 0;
            string sTag = sLine.Trim().Replace("【", "[").Replace("】", "]");
            sTag = sTag.Replace("[", string.Empty).Replace("]", string.Empty).Trim();
            if ((sTag.Length == 2) && sTag.EndsWith("."))
            {
                sTag = sTag.Replace(".", string.Empty).Trim();
            }
            return int.TryParse(sTag, out iIndex);
        }

        private int openSimpleFile(Dictionary<int, StrLineInfo> tDestList, string[] sSrtPiece)
        {
            if (tDestList == null)
                return -1;
            if ((sSrtPiece != null) && (sSrtPiece.Length > 0))
            {
                List<string> tList = new List<string>(sSrtPiece);
                for (int i = 0; i < tList.Count; i++)
                {
                    int iIndex = 0;
                    string sInfo = "";
                    if (chechIndex(tList[i], out iIndex))
                    {
                        for (int j = 1; j < tList.Count - i; j++)
                        {
                            int inewidx = -1;                            
                            if (!chechIndex(tList[i + j], out inewidx))
                                sInfo += tList[i + j].Trim() + "\r\n";
                            else
                                break;
                        }
                        //sInfo=sInfo.Replace(@"{N}", @"\N");
                        if (!tDestList.ContainsKey(iIndex))
                            tDestList.Add(iIndex, new StrLineInfo(iIndex, "", sInfo.Trim()));
                        else
                            tDestList[iIndex] = new StrLineInfo(iIndex, "", sInfo.Trim());
                    }
                }
                return tDestList.Count;
            }
            else
                return -2;
        }

        private int openSimpleFileASS(Dictionary<int, StrLineInfo> tDestList, string[] sSrtPiece)
        {
            if (tDestList == null)
                return -1;
            if ((sSrtPiece != null) && (sSrtPiece.Length > 0))
            {
                List<string> tList = new List<string>(sSrtPiece);
                for (int i = 0; i < tList.Count; i++)
                {
                    int iIndex = 0;
                    string sInfo = "";
                    if (chechIndex(tList[i], out iIndex))
                    {
                        for (int j = 1; j < tList.Count - i; j++)
                        {
                            int inewidx = -1;
                            if (!chechIndex(tList[i + j], out inewidx))
                                sInfo += tList[i + j].Trim() + "\r\n";
                            else
                                break;
                        }
                        if (!tDestList.ContainsKey(iIndex))
                            tDestList.Add(iIndex, new StrLineInfo(iIndex, "", sInfo.Trim()));
                        else
                            tDestList[iIndex] = new StrLineInfo(iIndex, "", sInfo.Trim());
                    }
                }
                return tDestList.Count;
            }
            else
                return -2;
        }


        private bool isTimeTag(out string[] tTimeList,string sInfo)
        {
            tTimeList = null;
            if ((tTimeList==null)&&(!string.IsNullOrEmpty(sInfo))
                &&(sInfo.Length>5)&&(sInfo.IndexOf("-")>0))
            {
                tTimeList = sInfo.Split('-');
                for (int i = 0; i < tTimeList.Length; i++)
                    tTimeList[i] = tTimeList[i].Trim().Replace(".", ",") + "0";
            }
            return (tTimeList != null) && (tTimeList.Length == 2);
        }

        private int modifyTSCYWFile(List<StrLineInfo> tDestList, string sFileName, int indexBase = 0)
        {
            if (tDestList != null)
            {
                tDestList.Clear();
                if (File.Exists(sFileName))
                {
                    string[] tTimeList = null;
                    List<string> tList = new List<string>(File.ReadAllLines(sFileName));
                    int iIndex = indexBase;

                    for (int i = 0; i < tList.Count; i++)
                        if (isTimeTag(out tTimeList, tList[i].Trim()))
                        {
                            iIndex++;
                            string sInfo = "";
                            string sTimSpace = tTimeList[0].Trim() + " --> " + tTimeList[1].Trim();
                            for (int j = 1; j < tList.Count - i - 1; j++)
                                if (!isTimeTag(out tTimeList, tList[i + j].Trim()))
                                {
                                    sInfo += tList[i + j].Trim() + "\r\n";
                                }
                                else
                                    break;
                            if (!string.IsNullOrEmpty(sInfo))
                            {
                                tDestList.Add(new StrLineInfo(iIndex, sTimSpace, sInfo.Trim()));
                            }
                        }
                    return tDestList.Count;
                }
                else
                    return -2;
            }
            return -1;
        }

        private async void buttonOpenMid_Click(object sender, EventArgs e)
        {
            int iCount = 0;
            tabControlSour.SelectedIndex = 0;
            if ((tSourInfoLines != null) && (tSourInfoLines.Count > 0))
            {
                if (File.Exists(textBoxCNSrt.Text))
                    iCount = openSimpleFile(tCNInfos, textBoxCNSrt.Text);
                else
                {
                    iCount = openSimpleFile(tCNInfos, richTextBoxSrtPiece.Lines);
                    richTextBoxSrtPiece.Clear();
                }
            }
            switch (iCount)
            {
                case 0:
                    MessageBox.Show("请先读取原始文件！", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    break;
                case -1:
                    MessageBox.Show("输入对象为空!", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    break;
                case -2:
                    MessageBox.Show("目标文件不存在!", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    break;
                case -3:
                    MessageBox.Show("对比错误!", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    break;
                case -4:
                    MessageBox.Show("数量错误!", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    break;
                default:
                    label翻译片段.Text = "翻译片段:" + iCount.ToString();
                    int iThdCount= await tAutoTrStr.AutoTRRun(tCNInfos);
                    MessageBox.Show("成功提取到信息：" + iThdCount.ToString());

                    buttonSaveSrt.Enabled = true;
                    break;
            }
        }

        private void textBoxCNSrt_DoubleClick(object sender, EventArgs e)
        {
            textBoxCNSrt.Text = "";
            if (openFileDialog1.ShowDialog() == DialogResult.OK)
            {
                textBoxCNSrt.Text = openFileDialog1.FileName;
            }
        }

        private void button1_Click(object sender, EventArgs e)
        {
            string sDestFileName = "";
            if (saveFileDialog1.ShowDialog(this) == DialogResult.OK)
            {
                sDestFileName = saveFileDialog1.FileName;
            }

            StringBuilder tSB = new StringBuilder();
            for (int i = 0; i < tSourInfoLines.Count; i++)
            {
                if ((!tSourInfoLines[i].hasTranslation) && tCNInfos.ContainsKey(tSourInfoLines[i].index))
                {
                    tSourInfoLines[i].context = tCNInfos[tSourInfoLines[i].index].context;
                }
                tSB.AppendLine(tSourInfoLines[i].toSrtLine());
            }

            if (!string.IsNullOrEmpty(sDestFileName))
                File.WriteAllText(sDestFileName, tSB.ToString());
            if (File.Exists(sDestFileName))
                MessageBox.Show("成功保存文件：" + sDestFileName);
        }

        private void button修正同声传译王_Click(object sender, EventArgs e)
        {
            int iCount = modifyTSCYWFile(tSourInfoLines, textBoxCNSrt.Text, 0);
            string sDestFileName = "";
            if (saveFileDialog1.ShowDialog(this) == DialogResult.OK)
            {
                sDestFileName = saveFileDialog1.FileName;
            }
            StringBuilder tSB = new StringBuilder();
            for (int i = 0; i < tSourInfoLines.Count; i++)
                tSB.AppendLine(tSourInfoLines[i].toSrtLine());
            if (!string.IsNullOrEmpty(sDestFileName))
                File.WriteAllText(sDestFileName, tSB.ToString());
            if (File.Exists(sDestFileName))
                MessageBox.Show("成功保存文件：" + sDestFileName);
        }

        private void buttonOllamaFY_Click(object sender, EventArgs e)
        {
            StringBuilder tOutputStr= new StringBuilder();
            Translator tTranslator= new Translator();
            tTranslator.TranslateStrAsync(
                inputStr: new StringBuilder(richTextBoxSourSimple.Text),
                outputStr: tOutputStr,
                sourceLang: "日语",
                targetLang: "中文"
            );
        }

        private void textBoxSourFile_DragDrop(object sender, DragEventArgs e)
        {
            // 获取拖放的文件路径
            string[] files = (string[])e.Data.GetData(DataFormats.FileDrop);

            if (files != null && files.Length > 0)
            {
                // 只处理第一个文件
                string filePath = files[0];

                // 显示文件路径
                textBoxSourFile.Text = filePath;
            }
        }

        private void textBoxSourFile_DragEnter(object sender, DragEventArgs e)
        {
            // 检查拖放的数据是否包含文件
            if (e.Data.GetDataPresent(DataFormats.FileDrop))
            {
                // 设置拖放效果为复制
                e.Effect = DragDropEffects.Copy;
            }
            else
            {
                // 不接受其他类型的拖放数据
                e.Effect = DragDropEffects.None;
            }
        }

        private void buttonOpenASS_Click(object sender, EventArgs e)
        {
            label翻译片段.Text = "";
            tabControlSour.SelectedIndex = 0;
            tCNInfos.Clear();
            tabControlSour.SelectedIndex = 0;
            int iCount = openASSFile(tSourInfoLines, textBoxSourFile.Text);
            switch (iCount)
            {
                case -1:
                    MessageBox.Show("输入对象为空!", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    break;
                case -2:
                    MessageBox.Show("目标文件不存在!", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    break;
                default:
                    MessageBox.Show("成功提取到信息：" + iCount.ToString());
                    buttonOpenMid.Enabled = true;
                    buttonSaveSrt.Enabled = false;
                    break;
            }
            // 展示精简字幕内容，保持标记序号，去掉时间戳，用于翻译
            if (iCount > 0)
            {
                richTextBoxSourSimple.Clear();
                for (int i = 0; i < iCount; i++)
                    if (!string.IsNullOrEmpty(tSourInfoLines[i].context))
                {
                    richTextBoxSourSimple.AppendText("[" + tSourInfoLines[i].index.ToString() + "]\r\n");
                    richTextBoxSourSimple.AppendText(tSourInfoLines[i].context + "\r");
                }
            }
        }

        private async void buttonOpenMASS_Click(object sender, EventArgs e)
        {
            int iCount = 0;
            tabControlSour.SelectedIndex = 0;
            if ((tSourInfoLines != null) && (tSourInfoLines.Count > 0))
            {
                if (File.Exists(textBoxCNSrt.Text))
                    iCount = openSimpleFile(tCNInfos, textBoxCNSrt.Text);
                else
                {
                    iCount = openSimpleFileASS(tCNInfos, richTextBoxSrtPiece.Lines);
                    richTextBoxSrtPiece.Clear();
                }
            }
            switch (iCount)
            {
                case 0:
                    MessageBox.Show("请先读取原始文件！", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    break;
                case -1:
                    MessageBox.Show("输入对象为空!", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    break;
                case -2:
                    MessageBox.Show("目标文件不存在!", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    break;
                case -3:
                    MessageBox.Show("对比错误!", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    break;
                case -4:
                    MessageBox.Show("数量错误!", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    break;
                default:
                    label翻译片段.Text = "翻译片段:" + iCount.ToString();
                    //int iThdCount = await tAutoTrStr.AutoTRRun(tCNInfos);
                    //MessageBox.Show("成功提取到信息：" + iThdCount.ToString());

                    buttonSaveSrt.Enabled = true;
                    break;
            }
        }

        private void buttonSaveASS_Click(object sender, EventArgs e)
        {
            string sDestFileName = "";
            if (saveFileDialog1.ShowDialog(this) == DialogResult.OK)
            {
                sDestFileName = saveFileDialog1.FileName;
            }

            StringBuilder tSB = new StringBuilder();
            for (int i = 0; i < tSourInfoLines.Count; i++)
            {
                string sResult = tSourInfoLines[i].timeTag;
                if ((!tSourInfoLines[i].hasTranslation) && tCNInfos.ContainsKey(tSourInfoLines[i].index))
                {
                    tSourInfoLines[i].timeTag = tSourInfoLines[i].timeTag.Replace(@"\N", " ");
                    sResult = tSourInfoLines[i].timeTag.Replace(tSourInfoLines[i].context, tCNInfos[tSourInfoLines[i].index].context);
                }
                tSB.AppendLine(sResult);
            }

            if (!string.IsNullOrEmpty(sDestFileName))
                File.WriteAllText(sDestFileName, tSB.ToString());
            if (File.Exists(sDestFileName))
                MessageBox.Show("成功保存文件：" + sDestFileName);
        }
    }

    public class StrLineInfo
    {
        public int index { get; set; } = 0;
        public string timeTag { get; set; } = "";
        public string context { get; set; } = "";

        public bool hasTranslation { get; private set; } = false;

        public StrLineInfo(int index, string timeTag, string context)
        {
            this.index = index;
            this.timeTag = timeTag;
            this.context = context;
        }

        public void setTranslation(string translation)
        {
            this.context = translation;
            this.hasTranslation = true;
        }

        public string toSrtLine()
        {
            return string.Format("{0}\r\n{1}\r\n{2}", index.ToString(), timeTag, context);
        }

        public string toASSLine()
        {
            
            return string.Format("{0}\r\n{1}\r\n{2}", index.ToString(), timeTag, context);
        }
    }
}
